package com.retail.order.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.retail.core.cache.CacheService;
import com.retail.core.entity.enums.DelFlagEnum;
import com.retail.core.entity.enums.StatusFlagEnum;
import com.retail.douyin.entity.po.TokTikAppParamRequest;
import com.retail.douyin.service.AccessTokenService;
import com.retail.order.entity.request.RetailSettleOrderRequest;
import com.retail.order.entity.vo.NameValueVo;
import com.retail.order.entity.vo.RetailOrderDailyStasticsVo;
import com.retail.order.entity.vo.RetailSettleOrderVo;
import com.retail.core.entity.ParamReq;
import com.retail.order.entity.vo.StatisticsOrderDetailVo;
import com.retail.order.enums.OrderStatusEnums;
import com.retail.order.enums.OrderTypeEnums;
import com.retail.order.mapper.RetailSettleOrderMapper;
import com.retail.order.service.RetailSettleOrderService;
import com.retail.shop.entity.vo.RetailShopVo;
import com.retail.shop.enums.ShopSourceEnums;
import com.retail.shop.mapper.RetailShopMapper;
import com.retail.system.entity.vo.AdminStatisticsShopVo;
import com.retail.system.entity.vo.AdminVo;
import com.retail.system.mapper.AdminMapper;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 订单信息 Service impl
 *
 * @author Administrator
 */
@Service
public class RetailSettleOrderServiceImpl implements RetailSettleOrderService {

    @Resource
    private RetailSettleOrderMapper retailSettleOrderMapper;

    @Resource
    private RetailShopMapper retailShopMapper;

    @Resource
    private AdminMapper adminMapper;

    @Override
    public RetailSettleOrderVo getModel(Long id) {
        RetailSettleOrderVo orderVo = retailSettleOrderMapper.getModel(id);
        orderVo.setOrderTypeName(OrderTypeEnums.getStatusValues(orderVo.getOrderType()));
        orderVo.setOrderStatusName(OrderStatusEnums.getStatusValues(orderVo.getOrderStatus()));
        duplicateAdmin(orderVo);
        return orderVo;
    }

    @Transactional
    @Override
    public Long save(RetailSettleOrderRequest retailOrderRequest) {
        retailSettleOrderMapper.save(retailOrderRequest);
        return retailOrderRequest.getId();
    }

    @Transactional
    @Override
    public Long update(RetailSettleOrderRequest retailOrderRequest) {
        retailSettleOrderMapper.update(retailOrderRequest);
        return retailOrderRequest.getId();
    }

    @Override
    public List<RetailSettleOrderVo> listPage(ParamReq<RetailSettleOrderRequest> params) {
        params.setStartIndex((params.getCurrent() - 1) * params.getSize());
        List<RetailSettleOrderVo> ret = retailSettleOrderMapper.listPage(params);
        ret.forEach(r -> {
            r.setOrderTypeName(OrderTypeEnums.getStatusValues(r.getOrderType()));
            r.setOrderStatusName(OrderStatusEnums.getStatusValues(r.getOrderStatus()));
            duplicateAdmin(r);
        });
        return ret;
    }

    @Override
    public Integer countPage(ParamReq<RetailSettleOrderRequest> params) {
        return retailSettleOrderMapper.countPage(params);
    }

    @Override
    public Integer updateDelFlagById(Long id, Integer delFlag) {
        return retailSettleOrderMapper.updateDelFlagById(id, delFlag);
    }

    @Override
    public RetailSettleOrderVo getModelByOrderIdAndSource(String orderId, Integer orderSource) {
        return retailSettleOrderMapper.getModelByOrderIdAndSource(orderId, orderSource);
    }

    @Override
    public List<RetailSettleOrderVo> findOwnerOrderByAdminId(String adminId) {
        List<RetailSettleOrderVo> ret = retailSettleOrderMapper.findOwnerOrderByAdminId(adminId);
        ret.forEach(r -> {
            r.setOrderTypeName(OrderTypeEnums.getStatusValues(r.getOrderType()));
            r.setOrderStatusName(OrderStatusEnums.getStatusValues(r.getOrderStatus()));
            duplicateAdmin(r);
        });

        return ret;
    }

    @Override
    public List<RetailSettleOrderVo> myOrderList(String adminId) {
        List<RetailSettleOrderVo> ret = retailSettleOrderMapper.myOrderList(adminId);
        ret.forEach(r -> {
            r.setOrderTypeName(OrderTypeEnums.getStatusValues(r.getOrderType()));
            r.setOrderStatusName(OrderStatusEnums.getStatusValues(r.getOrderStatus()));
            duplicateAdmin(r);
        });

        return ret;
    }

    @Override
    public List<RetailSettleOrderVo> myShopOrderList(String adminId) {
        List<RetailSettleOrderVo> ret = retailSettleOrderMapper.myShopOrderList(adminId);
        ret.forEach(r -> {
            r.setOrderTypeName(OrderTypeEnums.getStatusValues(r.getOrderType()));
            r.setOrderStatusName(OrderStatusEnums.getStatusValues(r.getOrderStatus()));
            duplicateAdmin(r);
        });

        return ret;
    }

    @Override
    public RetailSettleOrderVo getModelByOrderId(String orderId) {
        return retailSettleOrderMapper.getModelByOrderIdLimit1(orderId);
    }

    @Override
    public AdminStatisticsShopVo statisticsOrder(Long adminId) {
        return retailSettleOrderMapper.statisticsOrder(adminId);
    }

    @Override
    public List<RetailSettleOrderVo> findSuccessOwnerOrderByAdminId(String adminId) {
        List<RetailSettleOrderVo> orderList = retailSettleOrderMapper.findSuccessOwnerOrderByAdminId(adminId);
        orderList.forEach(order -> {
            order.setOrderTypeName(OrderTypeEnums.getStatusValues(order.getOrderType()));
            order.setOrderStatusName(OrderStatusEnums.getStatusValues(order.getOrderStatus()));
            duplicateAdmin(order);
        });

        return orderList;
    }
    @Override
    public List<RetailSettleOrderVo> findSuccessOwnerOrderByAdminIdAndId(String adminId) {
        List<RetailSettleOrderVo> orderList = retailSettleOrderMapper.findSuccessOwnerOrderByAdminIdAndId(adminId);
        orderList.forEach(order -> {
            order.setOrderTypeName(OrderTypeEnums.getStatusValues(order.getOrderType()));
            order.setOrderStatusName(OrderStatusEnums.getStatusValues(order.getOrderStatus()));
//            duplicateAdmin(order);
        });

        return orderList;
    }

    @Override
    public Map<String, Object> getOrderMonthStastics(Long adminId, Integer adminType, Long startTimestamp, Long endTimestamp) {
        return retailSettleOrderMapper.getOrderMonthStastics(adminId, adminType, startTimestamp, endTimestamp);
    }

    @Override
    public List<RetailOrderDailyStasticsVo> getDailyOrderMonthStastics(Long adminId, Integer adminType, Long startTimestamp, Long endTimestamp) {
        return retailSettleOrderMapper.getDailyOrderMonthStastics(adminId, adminType, startTimestamp, endTimestamp);
    }


    @Override
    public List<RetailSettleOrderVo> getOrdersByShop(String poiId) {
        List<RetailSettleOrderVo> ret = retailSettleOrderMapper.getOrdersByShop(poiId);
        ret.forEach(r -> {
            r.setOrderTypeName(OrderTypeEnums.getStatusValues(r.getOrderType()));
            r.setOrderStatusName(OrderStatusEnums.getStatusValues(r.getOrderStatus()));
            duplicateAdmin(r);
        });

        return ret;
    }

    @Override
    public List<RetailSettleOrderVo> findOwnerOrderByAdminIdNotInVerifDetail(Long adminId) {
        List<RetailSettleOrderVo> ret = retailSettleOrderMapper.findOwnerOrderByAdminIdNotInVerifDetail(adminId);
        ret.forEach(r -> {
            r.setOrderTypeName(OrderTypeEnums.getStatusValues(r.getOrderType()));
            r.setOrderStatusName(OrderStatusEnums.getStatusValues(r.getOrderStatus()));
            duplicateAdmin(r);
        });

        return ret;
    }

    private void duplicateAdmin(RetailSettleOrderVo r) {
        if (ObjectUtil.isNotEmpty(r.getPoiId())) {
            AdminVo adminVo = adminMapper.getModelByPoiId(r.getPoiId());
            if (ObjectUtil.isNotEmpty(adminVo)) {
                r.setAdminId(adminVo.getId());
                r.setAdminName(adminVo.getName());
            }
        }
    }

    @Resource
    private TokTikAppParamRequest tokTikAppParamRequest;

    @Resource
    private AccessTokenService accessTokenService;

    @Override
    public List<RetailSettleOrderRequest> syncTokTikOrderList(String billDate,List<RetailShopVo> allShops) {
        List<RetailSettleOrderRequest> retOrders = new ArrayList<>();
        for (RetailShopVo shop : allShops) {
            boolean hasMore = true;
            String cursor = "0";
            while (hasMore) {
                String accessToken = accessTokenService.createTikTokAccessToken();
                String content = requestDouyinOrderResContent(accessToken, shop.getAccountId(), billDate, cursor);
                JSONObject jsonObject = JSONObject.parseObject(content);

                JSONObject extra = jsonObject.getJSONObject("extra");
                Integer error_code = extra.getInteger("error_code");

                if (ObjectUtil.equal(error_code, 0)) {
                    JSONObject data = jsonObject.getJSONObject("data");
                    cursor = data.getString("cursor");
                    hasMore = data.getBoolean("has_more");
                    JSONArray orders = data.getJSONArray("ledger_records");
                    retOrders.addAll(orderResToOrderModel(orders));
                } else {
                    accessTokenService.removeTikTokAccessToken();
                    hasMore = false;
                }
            }
        }
        return retOrders;
    }

    @Override
    public Integer allOrders() {
        return retailSettleOrderMapper.allOrders();
    }

    @Override
    public Map<String, Object> orderFullStatisticsByAdminId(Long adminId) {
       return retailSettleOrderMapper.orderFullStatisticsByAdminId(adminId);
    }

    @Override
    public Map<String, Object> orderFullStatisticsByTuanduizId(Long adminId) {
        return retailSettleOrderMapper.orderFullStatisticsByTuanduizId(adminId);
    }

    @Override
    public List<StatisticsOrderDetailVo> orderFullStatistics(Long adminId, Integer userType, String startTime, String endTime, String dateType) {
        return retailSettleOrderMapper.orderFullStatistics(adminId, userType, startTime, endTime, dateType);
    }

    @Override
    public List<NameValueVo> orderShopStatistics(Long adminId, Integer userType, String startTime, String endTime, String dateType) {
        return retailSettleOrderMapper.orderShopStatistics(adminId, userType, startTime, endTime, dateType);
    }

    @Override
    public List<StatisticsOrderDetailVo> ordershopListFullStatistics(Long adminId, Integer userType, String startTime, String endTime, String dateType) {
        return retailSettleOrderMapper.ordershopListFullStatistics(adminId, userType, startTime, endTime, dateType);
    }

    private String requestDouyinOrderResContent(String accessToken, String accountId, String billDate, String cursor) {
        try {
            String url = tokTikAppParamRequest.getOrderClientUrl()
                    + "?account_id=" + accountId
                    + "&cursor=" + cursor
                    + "&size=50"
                    + "&bill_date=" + billDate;
            OkHttpClient client = new OkHttpClient().newBuilder().build();
            Request request = new Request.Builder()
                    .url(url)
                    .get()
                    .addHeader("access-token", accessToken)
                    .build();
            Response response = client.newCall(request).execute();
            assert response.body() != null;
            return response.body().string();
        } catch (Exception e) {
            return null;
        }
    }

    public List<RetailSettleOrderRequest> orderResToOrderModel(JSONArray orders) {
        List<RetailSettleOrderRequest> retOrders = new ArrayList<>();
        orders.stream().forEach(poio -> {
            JSONObject poiJ = (JSONObject) poio;
            RetailSettleOrderRequest request = new RetailSettleOrderRequest();
            request.setShopNumber(poiJ.getString("ledger_id"));
            request.setOrderId(poiJ.getString("shop_order_id"));
//                request.setOrderType(poiJ.getInteger("biz_type"));
            request.setOrderType(21);
            request.setOrderStatus(1);
            request.setAccountId(poiJ.getString("verify_poi_account_id"));
            if (ObjectUtil.isNotEmpty(request.getAccountId())) {
                RetailShopVo retailShopVo = retailShopMapper.getShopByAccountId(request.getAccountId());
                if (ObjectUtil.isNotEmpty(retailShopVo)) {
                    request.setAccountName(retailShopVo.getAccountName());
                }
            }
            request.setPoiId(poiJ.getString("poi_id"));
            if (ObjectUtil.isNotEmpty(request.getPoiId())) {
                RetailShopVo retailShopVo = retailShopMapper.getmodelByPoiIdAndSource(request.getPoiId(), ShopSourceEnums.DY_TYPE.getValue());
                if (ObjectUtil.isNotEmpty(retailShopVo)) {
                    request.setPoiName(retailShopVo.getPoiName());
                }
            }

            request.setNum(1L);
            request.setProductId(poiJ.getString("sku_id"));
            request.setProductName(poiJ.getString("group_name"));

            JSONObject amount = poiJ.getJSONObject("amount");
            if (ObjectUtil.isNotEmpty(amount)) {
                if (amount.containsKey("original")) {
                    request.setOriginalAmount(amount.getBigDecimal("original").divide(new BigDecimal(100)));
                }
                if (amount.containsKey("goods")) {
                    request.setReceiptAmount(amount.getBigDecimal("goods").divide(new BigDecimal(100)));
                }

                if (amount.containsKey("ledger_total")) {
                    request.setPaymentDiscount(amount.getBigDecimal("ledger_total").divide(new BigDecimal(100)));
                }

                if (amount.containsKey("pay")) {
                    request.setPayAmount(new BigDecimal(amount.get("pay") + "").divide(new BigDecimal(100)));
                }
            }
            request.setPayTime(poiJ.get("settle_time") + "");
            Date verifyTime = DateUtil.date(poiJ.getLong("settle_time") * 1000);
            request.setVerifyTime(DateUtil.format(verifyTime, "yyyy-MM-dd"));
            request.setOrderSource(ShopSourceEnums.DY_TYPE.getValue());
            request.setDelFlag(DelFlagEnum.NO.getValue());
            request.setStatusFlag(StatusFlagEnum.USE.getValue());
            if (ObjectUtil.isNotEmpty(request)) {
                retOrders.add(request);
            }
        });
        return retOrders;
    }
}
